/// \file
/// \brief \b [Internal] Memory pool for RtRudpPacket*
///
/// This file is part of RakNet Copyright 2003 Kevin Jenkins.
///
/// Usage of RakNet is subject to the appropriate license agreement.
/// Creative Commons Licensees are subject to the
/// license found at
/// http://creativecommons.org/licenses/by-nc/2.5/
/// Single application licensees are subject to the license found at
/// http://www.rakkarsoft.com/SingleApplicationLicense.html
/// Custom license users are subject to the terms therein.
/// GPL license users are subject to the GNU General Public
/// License as published by the Free
/// Software Foundation; either version 2 of the License, or (at your
/// option) any later version.

#ifndef __INTERNAL_PACKET_POOL
#define __INTERNAL_PACKET_POOL

#include "RtCnRudpBase.h"
#include "RtMessageBlock.h"
#include "RtMemoryPoolT.h"

struct RtRudpPacket
{
public:
	///A unique numerical identifier given to this user message
	RtRudpPacketNo packetNo;
	///The priority level of this packet
	IRtTransport::DataPriority priority;
	///What type of reliability algorithm to use with this packet
	RtRudpReliability reliability;
	///What ordering channel this packet is on, if the reliability type uses ordering channels
	unsigned char orderingChannel;
	///The ID used as identification for ordering channels
	RtRudpOrderingID orderingIndex;
	///The ID of the split packet, if we have split packets.  This is the maximum number of split messages we can send simultaneously per connection.
	RtRudpSplitPacketNo splitPacketId;
	///If this is a split packet, the index into the array of subsplit packets
	RtRudpSplitPacketID splitPacketIndex;
	///The size of the array of subsplit packets
	RtRudpSplitPacketID splitPacketCount;
	///When this packet was created
	RtRudpTimeUS creationTime;
/*
	///The next time to take action on this packet
	RtRudpTimeUS nextActionTime;
*/
	///The last send time of this packet
	RtRudpTimeUS lastSendTime;
	///Time-to-live value of the packet, in milliseconds
	INT ttl;
	///PDU type
	RtRudpPduType pduType;
	///PDU data
	CRtMessageBlock* data;
	/// For checking packetloss at a particular send rate
	unsigned histogramMarker;

public:
	RtRudpPacket()
		: data(NULL)
	{
		Release();
	}
	~RtRudpPacket()
	{
		if (data)
		{
			RUDP_ERROR_TRACE_THIS("RtRudpPacket::~RtRudpPacket, data not null! len="<<data->GetChainedLength());
			data->DestroyChained();
			data = NULL;
		}
	}
	void Release()
	{
		packetNo = 0;
		priority = IRtTransport::DP_MEDIUM;
		reliability = RUDP_UNRELIABLE;
		orderingChannel = 0;
		orderingIndex = 0;
		splitPacketId = 0;
		splitPacketIndex = 0;
		splitPacketCount = 0;
		creationTime = 0;
// 		nextActionTime = 0;
		lastSendTime = 0;
		ttl = 0;
		pduType = 0;
		if (data)
		{
			data->DestroyChained();
			data = NULL;
		}
		histogramMarker = 0;
	}
};

class CRtRudpPacketPool: public CRtMemoryPoolT<RtRudpPacket>
{
	typedef CRtMemoryPoolT<RtRudpPacket> BaseType;

public:
	CRtRudpPacketPool()
		: BaseType("RudpPackPool")
	{
		BaseType::Preallocate(64);
	}

private:
	CRtRudpPacketPool(const CRtRudpPacketPool&);
	CRtRudpPacketPool& operator = (const CRtRudpPacketPool&);
};

#endif

